<style scoped>
.outer{height: 100%;width: 100%;overflow: hidden;align-items: stretch;}
.type_map{height: 100%;overflow: auto;width: 300px;}

.type_list{flex-wrap: wrap;align-items: stretch;padding: 5px;user-select: none;}
.type_list .row{flex-direction: column;width: 120px;margin: 5px;font-size: 14px;text-align: center;border-radius: 05px;cursor: pointer;overflow: hidden;transition: transform 0.4s;}
.type_list .row .head_img{height: 60px;padding-top: 4px;}
.type_list .row:hover{box-shadow: 0 0 02px 02px var(--color-primary);}

.display{height: 100%;}
.drag_ing{position: relative;}
.drag_ing::after{content: '';position: absolute;left: 0;top: 0;width: 100%;height: 100%;z-index: 999;}

.phone-outer{box-sizing: border-box;width: 395px;height: 100%;border: 10px solid #000;border-radius: 20px;overflow: hidden;align-items: stretch;}
#mobile-frame {
  width: 100%;
  height: 100%;
  -ms-overflow-style: none;
  scrollbar-width: none;
}
/* 隐藏所有滚动条 */
#mobile-frame::-webkit-scrollbar {
  display: none;
}

.form-box{flex-direction: column;align-items: stretch;height: 100%;overflow: hidden;}
.form-box .change{padding: 5px 20px;justify-content: space-between;}
.demo-tabs{overflow: hidden;padding-left: 2px;}

.json_display{width: 100%;max-height: 500px;overflow: auto;}
.json_display pre{line-height: 1.2;}

</style>
<template>
  <div class="outer flex">
    <div class="type_map">
      <el-tabs :model-value="Object.keys(type_group)[0]">
        <el-tab-pane :label="group" :name="group" v-for="(type_list, group) in type_group">
          <ul class="flex type_list">
            <li v-for="row in type_list" class="row flex" draggable="true" @dragstart="dragstart(row)" @dragend="dragend" :title="row.tip">
              <img class="head_img" v-if="row.head_img" :src="row.head_img" alt="">
              <p>{{row.name}}</p>
              <p>{{row.title}}</p>
            </li>
          </ul>
        </el-tab-pane>
      </el-tabs>
    </div>
    <div class="display"  @dragover.prevent="">
      <div class="phone-outer flex" style="flex-direction: column;">
        <img src="@/assets/img/phone-head.png" style="width: 100%;">
        <div class="max" :class="{drag_ing:dragIng}" @drop="drop($event)">
          <iframe ref="iframe" id="mobile-frame" src="" frameborder="0"></iframe>
        </div>
      </div>
    </div>

    <div class="form-box max flex">
      <div class="change flex">
        <p>切换到：<el-button :type="selectAble?'default':'primary'" :disabled="is_info" @click="selectAble=!selectAble">{{selectAble?'浏览模式':'编辑模式'}}</el-button></p>
        <el-button @click="restore">恢复默认</el-button>
      </div>
      <el-tabs v-model="tab" class="demo-tabs max" @tab-click="">
        <el-tab-pane label="板块参数" name="block">
          <forms ref="forms" v-show="show_forms" @change="update" @submit:forms="update" :config="form_config" :btns="form_btns"></forms>
        </el-tab-pane>
        <el-tab-pane label="页面参数" name="page">
          <forms ref="page_form" :config="page_form" :btns="page_form_btns" @submit:forms="onsubmit">
            <template #config_json="{row}">
              <div class="json_display">
                <pre>{{ JSON.stringify(row.value, null, 2) }}</pre>
              </div>
            </template>
          </forms>
        </el-tab-pane>
      </el-tabs>

    </div>

  </div>
</template>
<script>
import {confirm, href_handle, iframe, msg} from "@/js/tool.js";
import Forms from "@/components/forms.vue";
import {ajax} from "@/js/api_tool.js";
import {_url_api, json_decode_object, json_encode, to_string, unifyEnv} from "@/js/s94_tool.js";
import s94Mjs from "s94-js";
import {use_config_map} from "@/store/config_map.js";

export default {
  components: {Forms},
  props: ['__iframe'],
  data(){
    let app = this, id = this.$get('id');
    let is_info = !!this.$get('is_info');
    let channel = this.$get('channel');
    const channel_map = use_config_map().status_alias_map?.page?.channel || {};
    if (!channel_map[channel]) {
      channel = Object.keys(channel_map)[0] || '';
    }
    let form_btns = [
      {title:'删除', type:'danger', onclick:()=>{ this.delete(); }},
    ];
    let page_form = {
      title: {name:'title', label:'标题', type:'text_one',value:''},
      url: {name:'url', label:'URL', type:'text_one', tips:'页面地址示例，影响板块参数的$input',value:''},
      channel: {name:'channel', label:'所属渠道', type:'radio', config:channel_map, tips:'',value:channel},
      type: {name:'type', label:'类型', type:'radio', config:'默认|,首页|index,个人中心|user_index',  tips:'',value:''},
      config: {name:'config', label:'页面配置', type:'config_json', tips:'',value:[]},
    }
    let page_form_btns = undefined;
    if (is_info){
      Object.values(page_form).forEach(row=>row.is_info=true)
      page_form_btns = [];
    }
    return {
      id,
      is_info,
      inited: false,

      page_info: {
        config: [],
        info: {}
      }, //页面配置详情，包含：config，info

      page_form,
      page_form_btns,

      tab: 'page',

      form_config: [],
      form_btns: form_btns,
      componentConfigMap: {},

      dragIng: false,
      addType: null,
      pageBlock: null,
      selectAble: !is_info,
    }
  },
  methods: {
    postMessage(type, data){
      data = JSON.parse(JSON.stringify(data));
      this.$refs.iframe.contentWindow.postMessage({type,data}, '*');
    },
    iframe_src(){
      console.log('-------iframe_src---------')
      let arr = [];
      let url = to_string(this.page_form.url.value);
      url.replace(/\?([^?#]+)/g, (p0,p1)=>{
        p1 && arr.push(p1);
      })
      let search = arr.join('&');

      let channel = this.page_form.channel.value;
      const env_name = `PAGE_DISPLAY_${channel}`.toUpperCase();
      let display_url = unifyEnv(env_name, `/${channel}/#/page_block_display`);
      display_url = display_url + (~display_url.indexOf('?')?'&':'?') + search;
      return display_url;
    },
    async getInfo(){
      if (!this.id) return null;
      return new Promise((resolve, reject) => {
        ajax(`/admin/page/info?id=${this.id}`, ({data})=>{
          data.config = data.config_json ? Object.values(json_decode_object(data.config_json)) : [];
          this.$refs.page_form.init(data);
          this.page_info = data;
          resolve(data);
          return false;
        }, ()=>{
          if (this.__iframe){
            iframe.remove('page/edit');
          }else {
            href_handle(-1);
          }
        })
      })
    },
    async init(){
      this.postMessage('init', {
        ...this.page_info,
        selectAble: this.selectAble,
      });
      if (!this.selectAble) {
        this.postMessage('selectAble', this.selectAble);
      }
    },
    select(pageBlock){
      this.pageBlock = pageBlock;
      if (!pageBlock) return;
      let typeConfig = this.componentConfigMap[pageBlock.type];
      if (!typeConfig){
        this.pageBlock = null;
        return msg.fail(`组件类型不存在：${pageBlock.type}`);
      }
      let formConfig = [
        {name:'', label:'组件', value:`【${typeConfig.group||'未分组'}】${typeConfig.title}`, tips:typeConfig.tip},
        {name:'_style_', label:'样式', value:'', type:'text_one', tips:'css样式，设备宽度=375px=3.75rem'}, //这里如果name=style，会影响表单的show切换渲染
      ]
      // 处理参数对应的表单
      let def_type = 'text_one_code';
      Object.values(typeConfig.param_map).forEach(row=>{
        //组件类型确定
        let type_arr = [];
        if (row.input_type) {
          type_arr = typeof row.input_type === 'string' ? [{_type_:row.input_type}] : Object.values(row.input_type);
        }else if (row.is_boolean) {
          // 对于boolean参数，没有指定 输入组件的情况下，使用 radio_switch
          type_arr.push({_type_:'radio_switch', config:'否|,是|1'})
        }
        if (!type_arr.some(row=>row._type_===def_type)){
          type_arr.push({_type_:'text_one_code'})
        }
        let configRow = {
          name: row.name,
          label: row.label,
          value: '',
          type: type_arr,
          tips: row.tip,
        }
        if (row.is_required){
          configRow.validate = ['required'];
        }
        formConfig.push(configRow)
      })
      this.form_config = formConfig;
      console.log(formConfig, '--------formConfig-----------')
      setTimeout(()=>{
        this.$refs.forms.set_init_value();
        this.tab = 'block';
        pageBlock.props._style_ = pageBlock.props.style; // 表单回显的时候，给 _style_ 赋值
        this.$refs.forms.init(pageBlock.props)
      },20)
    },
    update(){
      if (!this.pageBlock) return;
      let page_block_id = this.pageBlock.page_block_id;
      let props = this.$refs.forms.form_data();
      props.style = props._style_;
      delete props._style_;
      this.postMessage('update', {page_block_id, props});
    },
    delete(){
      if (!this.pageBlock) return;
      confirm('是否确定删除此板块').then(()=>{
        this.postMessage('delete', this.pageBlock);
        this.pageBlock = null;
      }).catch(()=>{});
    },
    dragstart(row){
      this.dragIng = true;
      this.addType = row.name;
    },
    dragend(e){
      this.dragIng = false;
    },
    drop(e){
      let data = {
        x: e.offsetX,
        y: e.offsetY,
        type: this.addType,
      }
      this.selectAble = true;
      this.postMessage('add', data);
    },
    changeAfter(page_block_list){
      if (!this.page_info) return;
      //去除每一项的page_block_id和class
      s94Mjs.eachloop(page_block_list, 'children', (row)=>{
        delete row.page_block_id;
        delete row.class;
        return true;
      })
      this.page_info.config = page_block_list;
      this.page_form.config.value = page_block_list;
    },
    restore(){
      this.inited = false;
      this.$refs.iframe.src = this.iframe_src();
    },

    onsubmit(formData){
      let data = this.$refs.page_form.form_data();
      data.config_json = json_encode(data.config);
      delete data.config;
      let url = this.id ? `/admin/page/edit?id=`+this.id : '/admin/page/add';
      ajax({url:url, method:'POST', data}, (res)=>{
        iframe.exe('page/index', '$refs.list_url.list');
        this.$page_back();
      }, (res)=>{
        if (res.errors) this.$refs['forms'].errors = res.errors;
      })

    }
  },
  watch: {
    selectAble(){
      this.postMessage('selectAble', this.selectAble);
    },
    'page_form.url.value'(v){
      this.$refs.iframe.src = this.iframe_src();
      this.init();
    },
    'page_form.channel.value'(v){
      this.$refs.iframe.src = this.iframe_src();
      this.init();
    },
  },
  computed: {
    show_forms(){
      return this.pageBlock && this.selectAble;
    },
    type_group(){
      let res = {};
      Object.values(this.componentConfigMap).forEach(row=>{
        let group = row.group || '未分组';
        if (!res[group]) res[group] = [];
        res[group].push(row);
      })
      return res;
    }
  },
  mounted() {
    let app = this;
    if (!this.__iframe) window['app'] = this;

    if (!this.page_form.channel.value){
      return this.$page_back()
    }

    this.getInfo().then(data => {
      if (!data) this.$refs.iframe.src = this.iframe_src();
    })

    let onMessage = (event)=>{
      // 建议检查来源
      // if (event.origin !== 'https://trusted-origin.com') return;

      let {type, data} = event.data;
      switch (type){
        case 'select': this.select(data); break;
        case 'changeAfter': this.changeAfter(data); break;
        case 'componentConfigMap': {
          this.inited = true;
          this.init();
          this.componentConfigMap = data;
        } break;
      }

    };
    window.addEventListener('message', onMessage);
    this.onMessage = onMessage;
  },
  unmounted() {
    if(this.onMessage) window.removeEventListener('message', this.onMessage)
  }
}
</script>
